﻿using Heroius.Extension;
using Heroius.Files;
using Heroius.Files.CSV;
using Microsoft.Win32;
using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace AlbumDesign
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();

            Proj = new Proj();

            string proj_filter = "*.ad|*.ad";
            dias_proj = new SaveFileDialog() { Filter = proj_filter };
            diao_proj = new OpenFileDialog() { Filter = proj_filter };

            diao_ph = new OpenFileDialog() { Filter = "*.csv|*.csv" };

            Proj.Navi.PropertyChanged += Navi_PropertyChanged;

            DataContext = this;

            UpdateSelectStatus();
        }

        public Proj Proj { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChangedEvent(string PropertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
        }

        #region Proj

        private void NewProj_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Current album and photos will be cleared! Continue?", "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.Yes)
            {
                Proj.ResetNew();
                Proj.Navi.ToFirst();
            }
        }

        SaveFileDialog dias_proj;
        private void SaveProj_Click(object sender, RoutedEventArgs e)
        {
            if (dias_proj.ShowDialog() == true)
            {
                EntitySilo silo = new EntitySilo();
                silo.AutoStore = false;
                silo.Recursion = true;
                silo.StoreElements = true;
                var r = silo.Store("default", Proj);
                if (r)
                    silo.Save(dias_proj.FileName);
                else
                    MessageBox.Show("Err while store");
            }
        }

        OpenFileDialog diao_proj;
        private void LoadProj_Click(object sender, RoutedEventArgs e)
        {
            if (diao_proj.ShowDialog() == true)
            {
                EntitySilo silo = new EntitySilo();
                silo.AutoStore = false;
                silo.Recursion = true;
                silo.StoreElements = true;
                silo.Load(diao_proj.FileName);
                var r = silo.Fetch("default", Proj);

                if (r)
                {
                    Proj.Navi.ToFirst();
                }
                else
                {
                    MessageBox.Show("Err while fetch.");
                }
            }
        }

        #endregion

        #region Def

        private void DefAlbum_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Shrink of page or decrease of page count will lead to photo withdraw!");

            AlbumGuideWindow win = new AlbumGuideWindow(Proj.Album);
            if (win.ShowDialog() == true)
            {
                bool proceed = true;
                //validation
                if (win.A.Height < Proj.Album.Height || win.A.Width < Proj.Album.Width || win.A.DesignPageCount < Proj.Album.DesignPageCount)
                {
                    if (MessageBox.Show("Shrink of page or decrease of page count will lead to photo withdraw! Proceed?", "Note", MessageBoxButton.OKCancel, MessageBoxImage.Asterisk) == MessageBoxResult.OK)
                    {
                        proceed = true;
                        Proj.WithdrawPhotos();
                    }
                    else
                    {
                        proceed = false;
                    }
                }
                if (proceed)
                {
                    Proj.Album.Height = win.A.Height;
                    Proj.Album.Width = win.A.Width;
                    Proj.Album.DesignPageCount = win.A.DesignPageCount;
                    Proj.Album.ReGenPages();

                    Proj.Navi.ToFirst();
                }
            }

        }

        OpenFileDialog diao_ph;
        private void DefPhoto_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Load phote def file will clear all current photos!");
            if (diao_ph.ShowDialog() == true)
            {
                Proj.WithdrawPhotos();
                Proj.PhotoPool.Clear();
                try
                {
                    using (StreamReader sr = new StreamReader(diao_ph.FileName, Encoding.UTF8))
                    {
                        sr.ReadLine(); //header line
                        while (!sr.EndOfStream)
                        {
                            var parts = CsvHelper.ReadLine(sr.ReadLine());
                            Photo ph = new Photo()
                            {
                                ID = parts[0],
                                Height = parts[1].As<int>(),
                                Width = parts[2].As<int>(),
                                Group = parts[3].As<int>(),
                                Description = parts[4]
                            };

                            Proj.PhotoPool.AddPhoto(ph);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        #endregion

        #region Page Navi

        private void FirstPage_Click(object sender, RoutedEventArgs e)
        {
            Proj.Navi.ToFirst();
        }

        private void PrevPage_Click(object sender, RoutedEventArgs e)
        {
            Proj.Navi.ToPrev();
        }

        private void ToPage_Click(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.Enter)
            {
                int p = IupPn.Value.As<int>();
                Proj.Navi.To(p);
            }
        }

        private void NextPage_Click(object sender, RoutedEventArgs e)
        {
            Proj.Navi.ToNext();
        }

        private void LastPage_Click(object sender, RoutedEventArgs e)
        {
            Proj.Navi.ToLast();
        }

        #endregion

        #region Presentation

        private void Navi_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            switch (e.PropertyName)
            {
                case "CurrentPage":
                    {
                        PageBoard.Children.Clear();
                        foreach (var p in Proj.Navi.CurrentPage.Photoes)
                        {
                            AddPhotoRectInBoard(p);
                        }
                        IupPn.Value = Proj.Navi.CurrentPageNo;
                    }
                    break;
            }
        }

        private void AddPhotoRectInBoard(Photo p)
        {
            Rectangle rect = new Rectangle()
            {
                Height = p.Height,
                Width = p.Width,
                StrokeThickness = 1,
                Stroke = new SolidColorBrush(Colors.Black),
                Fill = new SolidColorBrush(Colors.Orange),
                ToolTip = $"ID: {p.ID}\r\nGroup: {p.Group}\r\n{p.Description}\r\nh{p.Height}*w{p.Width}",
                DataContext = p
            };
            rect.SetValue(Canvas.LeftProperty, p.PosX);
            rect.SetValue(Canvas.TopProperty, p.PosY);

            rect.MouseDown += Rect_MouseDown;
            rect.MouseMove += Rect_MouseMove;
            rect.MouseUp += Rect_MouseUp;

            PageBoard.Children.Add(rect);
        }

        private void RemovePhotoRectInBoard(Photo p)
        {
            Rectangle tar = null;
            foreach (Rectangle rect in PageBoard.Children)
            {
                if (rect.DataContext == p)
                {
                    tar = rect;
                    break;
                }
            }
            if (tar != null)
            {
                PageBoard.Children.Remove(tar);
            }
        }

        Nullable<Point> PosCache = null;

        private void Rect_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var rect = sender as Rectangle;
            PosCache = e.GetPosition(rect);
            SelectCache = rect.DataContext as Photo;
            UpdateSelectStatus();
            rect.CaptureMouse();
        }

        private void Rect_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            if (PosCache != null && e.LeftButton == System.Windows.Input.MouseButtonState.Pressed)
            {
                var rect = sender as Rectangle;
                var p2 = e.GetPosition(PageBoard);
                Canvas.SetLeft(rect, p2.X - PosCache.Value.X);
                Canvas.SetTop(rect, p2.Y - PosCache.Value.Y);
            }
        }

        private void Rect_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var rect = sender as Rectangle;
            SelectCache.PosX = Canvas.GetLeft(rect);
            SelectCache.PosY = Canvas.GetTop(rect);
            PosCache = null;
            rect.ReleaseMouseCapture();
        }

        #endregion

        #region Page Interact

        Photo SelectCache = null;

        private void PoolSelect_Down(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            SelectCache = (sender as FrameworkElement).DataContext as Photo;
            UpdateSelectStatus();
        }

        private void UpdateSelectStatus()
        {
            if (SelectCache == null)
            {
                StSelect.Content = "No photo selected.";
            }
            else
            {
                StSelect.Content = $"Selected photo ID: {SelectCache.ID} .";
            }
        }

        private void Mov2Page_Click(object sender, RoutedEventArgs e)
        {
            //validation neeeded
            if (SelectCache != null && Proj.PhotoPool.ContainsPhoto(SelectCache))
            {
                Proj.MovPhotoFromPoolToPage(SelectCache);
                AddPhotoRectInBoard(SelectCache);
            }
            else
            {
                MessageBox.Show("Selected photo not in pool.");
            }
        }

        private void MovAll2Page_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Move all photos on current group?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                //validation neeeded
                if (SelectCache != null && Proj.PhotoPool.ContainsPhoto(SelectCache))
                {
                    var g = Proj.PhotoPool.Where(p => p.ID == SelectCache.Group).First();
                    int c = g.Photos.Count();
                    for (int i = c - 1; i >= 0; i--)
                    {
                        var p = g.Photos.ElementAt(i);
                        Proj.MovPhotoFromPoolToPage(p);
                        AddPhotoRectInBoard(p);
                    }
                }
                else
                {
                    MessageBox.Show("Selected photo not in pool.");
                }
            }
        }

        private void Mov2Pool_Click(object sender, RoutedEventArgs e)
        {
            //validation needed
            if (SelectCache != null && Proj.Navi.CurrentPage.Photoes.Contains(SelectCache))
            {
                Proj.MovPhotoFromPageToPool(SelectCache);
                RemovePhotoRectInBoard(SelectCache);
            }
            else
            {
                MessageBox.Show("Selected photo not in current page.");
            }
        }

        private void MovAll2Pool_Click(object sender, RoutedEventArgs e)
        {
            if (MessageBox.Show("Move all photos on current page?", "Confirm", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                //validation needed
                if (SelectCache != null && Proj.Navi.CurrentPage.Photoes.Contains(SelectCache))
                {
                    int c = Proj.Navi.CurrentPage.Photoes.Count;
                    for (int i = c - 1; i >= 0; i--)
                    {
                        var p = Proj.Navi.CurrentPage.Photoes[i];
                        Proj.MovPhotoFromPageToPool(p);
                        RemovePhotoRectInBoard(p);
                    }
                }
                else
                {
                    MessageBox.Show("Selected photo not in current page.");
                }
            }
        }


        #endregion


    }
}
